#pragma once

#include <vector>
#include <map>
#include <string>
#include "hgesprite.h"
#include "guichan.hpp"
#include "singleton.h"

#define MAX_WP_BOX 1
#define MAX_CL_BOX 1
#define MAX_SOUND_NAME 32

class hgeSprite;
struct FrameData
{
	FrameData()
	{
		memset(this, 0, sizeof(FrameData));
		frametime = 0;
		texid = -1;
		memset( collisionbox, 0, sizeof(RECT)*MAX_CL_BOX );
		memset( weaponbox, 0, sizeof(RECT)*MAX_WP_BOX );
		ustart=vstart=0.0f;
		uend=vend=1.0f;
	}
	int frametime;
	int texid;
	float ustart;
	float vstart;
	float uend;
	float vend;
	RECT collisionbox[MAX_CL_BOX];
	RECT weaponbox[MAX_WP_BOX];
	int offsetx;
	int offsety;
	char sound[MAX_SOUND_NAME];
};

struct Frame
{
	Frame()
	{
		memset(this, 0, sizeof(Frame));
		frametime = 0;
		memset( collisionbox, 0, sizeof(RECT)*MAX_CL_BOX );
		memset( weaponbox, 0, sizeof(RECT)*MAX_WP_BOX );
	}
	Frame( const FrameData &data )
	{
		*this = data;
	}
	Frame( const Frame &frame )
	{
		frametime = frame.frametime;
		sprite = 0;
		for( int i=0;i<MAX_CL_BOX;i++ )
		{
			collisionbox[i] = frame.collisionbox[i];
		}
		for( int i=0;i<MAX_WP_BOX;i++ )
		{
			weaponbox[i] = frame.weaponbox[i];
		}
		offsetx = frame.offsetx;
		offsety = frame.offsety;
		strcpy(sound, frame.sound);
		if( frame.sprite )
		{
			sprite = new hgeSprite(*frame.sprite);
		}
	}
	Frame operator=( const FrameData &data )
	{
		frametime = data.frametime;
		sprite = 0;
		for( int i=0;i<MAX_CL_BOX;i++ )
		{
			collisionbox[i].x = data.collisionbox[i].left;
			collisionbox[i].y = data.collisionbox[i].top;
			collisionbox[i].width = data.collisionbox[i].right - data.collisionbox[i].left;
			collisionbox[i].height = data.collisionbox[i].bottom - data.collisionbox[i].top;
		}
		for( int i=0;i<MAX_WP_BOX;i++ )
		{
			weaponbox[i].x = data.weaponbox[i].left;
			weaponbox[i].y = data.weaponbox[i].top;
			weaponbox[i].width = data.weaponbox[i].right - data.weaponbox[i].left;
			weaponbox[i].height = data.weaponbox[i].bottom - data.weaponbox[i].top;
		}
		offsetx = data.offsetx;
		offsety = data.offsety;
		strcpy(sound, data.sound);
		return *this;
	}
	~Frame()
	{
		if( sprite )
		{
			delete sprite;
			sprite = 0;
		}
	}
	int frametime;
	hgeSprite *sprite;
	gcn::Rectangle collisionbox[MAX_CL_BOX];
	gcn::Rectangle weaponbox[MAX_WP_BOX];
	int offsetx;
	int offsety;
	char sound[MAX_SOUND_NAME];
};

typedef std::vector<Frame> FrameVec;
class Animation
{
public:
	enum{ONCE=0,LOOP,};
	Animation();
	Animation( const Animation &anim );
	~Animation();
	void Update( int diff );
	void Render( int x, int y, int layer, int direction, int w=-1, int h=-1 );
	void Start();
	Frame *GetCurFrame();
	bool IsEnd();
	
	FrameVec mFrames;
	int mPlaytype;
	int mCurframe;
	int mPassed;
	char mInterpolated;
	std::string mName;
};
typedef std::map<std::string, Animation*> AnimMap;
class AnimSet
{
public:
	AnimSet();
	AnimSet( const AnimSet &animset );
	~AnimSet();
	bool Load( const char *name );
	bool Play( std::string name );
	void Update( int diff );
	void Render( int x, int y, int layer );
	void Render( int x, int y,int w, int h, int layer );
	gcn::Rectangle GetCollisionBox();
	gcn::Rectangle GetBoundBox();
	gcn::Rectangle GetWeaponBox();
	void AdjustBoxDirection( gcn::Rectangle &r );
	void SetDirection( int direction );

	int mDirection;
	AnimMap mAnims;
	Animation *mCurAnim;
};

typedef std::map<std::string, AnimSet*> AnimSetMap;
class AnimManager:public CSingleton<AnimManager>
{
	IMPLEMENT_SINGLETON(AnimManager);
public:
	AnimSet *Load( const char *name );

	AnimSetMap mAnimSets;
};